﻿// -----------------------------------------------------------------------
// <copyright file="FormMove.cs" company="Abyssalsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Gui.BaseForm
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Windows.Forms;

    /// <summary>
    /// This is used to move the forms (When using this class, the forms will not stick!)
    /// </summary>
    public class FormMove
    {
        /// <summary> Lock synchronization object. </summary>
        private static readonly object Padlock = new object();

        /// <summary> Stores the current instance of this class </summary>
        private static FormMove instance = null;

        /// <summary> The point where the moving is started </summary>
        private Point refPoint;
 
        /// <summary> Used to move forms simultaneously </summary>
        private Gui.BaseForm.FormConnector connector;

        /// <summary> The form to move </summary>
        private Form currentForm;

        private bool startedMoving;

        /// <summary> Gets the current instance of this class (Singleton - Thread safety)... With double check! </summary>
        public static FormMove Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (Padlock)
                    {
                        if (instance == null)
                        {
                            instance = new FormMove();
                        }
                    }
                }

                return instance;
            }
        }

        /// <summary>
        /// Get the reference point (Should be called on MouseDown)
        /// </summary>
        /// <param name="e">Object sender</param>
        /// <param name="form">Event args</param>
        public void Start(System.Windows.Forms.MouseEventArgs e, System.Windows.Forms.Form form)
        {
            this.startedMoving = true;

            if (this.connector != null)
            {
                this.connector.Release();
            }

            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                // Connect forms to this form (to move them all together)
                this.currentForm = form;
                this.connector = new Gui.BaseForm.FormConnector(this.currentForm);
                this.ConnectForms();

                // Get the reference point
                this.refPoint = new Point(e.X, e.Y);
            }
        }

        /// <summary>
        /// Moves the form (Should be called on MouseMove)
        /// </summary>
        /// <param name="e">Mouse event args</param>
        /// <param name="form">The form to be moved</param>
        public void Move(System.Windows.Forms.MouseEventArgs e, System.Windows.Forms.Form form)
        {
            if (this.startedMoving)
            {
                if (form == null)
                {
                    return;
                }

                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    form.Left += e.X - this.refPoint.X;
                    form.Top += e.Y - this.refPoint.Y;
                }
            }
        }

        /// <summary>
        /// Stop moving the form (called on MouseUp)
        /// </summary>
        public void Stop()
        {
            this.startedMoving = false;

            if (this.connector != null)
            {
                this.connector.Release();
            }
        }

        /// <summary>
        /// "Connect" to all forms in the application, to move them together
        /// </summary>
        public void ConnectForms()
        {
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            foreach (Form form in Application.OpenForms)
            {
                // Connect all forms to MainForm
                if (this.currentForm != null)
                {
                    if (form.Name != this.currentForm.Name)
                    {
                        this.connector.ConnectForm(form);
                    }
                }
            }
        }
    }
}
